﻿using System;
using System.Linq;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Diagnostics;

namespace QuickShot.Shortcut
{
    public sealed class HotkeyManager : NativeWindow, IDisposable
    {
        public IDictionary<GlobalHotkey, Action> Hotkeys { get; set; }

        public HotkeyManager()
        {
            CreateHandle(new CreateParams());
        }

        public void RegisterHotkeys()
        {
            foreach (var hotkey in Hotkeys)
                if (!hotkey.Key.Register())
                    throw new HotkeyAlreadyRegisteredException(hotkey.Key.Hotkey);
        }

        public void UnregisterHotkeys()
        {
            foreach (var hotkey in Hotkeys)
                hotkey.Key.Unregister();
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == Constants.WM_HOTKEY)
            {
                Hotkey hotkey = new Hotkey((Modifiers)((uint)m.LParam & 0xFFFF), (Keys)((uint)m.LParam >> 16));
                foreach (var regHotkey in Hotkeys.Where(hk => hk.Key.Hotkey == hotkey))
                    regHotkey.Value();
            }
            base.WndProc(ref m);
        }

        public static Modifiers MapModifiers(Keys key)
        {
            Modifiers mod = Modifiers.None;
            foreach (Keys name in (Enum.GetValues(typeof(Keys)) as Keys[]))
                if ((name != Keys.None) && ((key & name) == name))
                    mod |= (Modifiers)Enum.Parse(typeof(Modifiers), name.ToString());

            return mod;
        }

        public static Keys MapKeys(Modifiers modifier)
        {
            Keys key = Keys.None;
            foreach (Modifiers name in (Enum.GetValues(typeof(Modifiers)) as Modifiers[]))
                if ((name != Modifiers.None) && ((modifier & name) == name))
                    key |= (Keys)Enum.Parse(typeof(Keys), name.ToString());

            return key;
        }

        public void Dispose()
        {
            DestroyHandle();
        }
    }
}
